Глава
11
Работа
с данными
Необходимо
подчеркнуть, что если вам доводилось разрабатывать программы по обработке баз
данных, используя язык SQL, то изучение данного материала не составит для вас
особой сложности.
Замечание
Все
примеры в данной главе основаны на разработанной нами базе данных CRUISE, описанной
в разд. "Разработка базы данных" гл. 5. В примерах могут встречаться
ссылки на основные файлы в рамках проекта "My-Line Cruises", коды
которых представлены в приложении 1.
Как уже отмечалось
ранее, ColdFusion позволяет работать с данными через драйверы ODBC, OLE DB,
а также использовать собственные драйверы для Oracle, Sybase, Informix, DB2.
Для реализации представленных здесь примеров мы предварительно создали источник
ODBC с именем Cruise в соответствии с наименованием базы данных.
Напомним,
что нами была разработана физическая модель базы данных CRUISE для сайта, знакомящего
туристов с возможными круизами и экскурсиями, позволяющего бронировать и распространять
билеты на текущие круизы.
Также отметим,
что при перемещении физической модели CRUISE непосредственно на сервер БД Sybase
SQL Anywhere было предложено изменить название таблицы SCHEDULE в связи с требованиями
конкретного сервера БД. Поэтому далее таблица, содержащая расписание, будет
именоваться как SCHEDULED В таком случае окончательный список таблиц, с которыми
предстоит работать, выглядит так:
В ColdFusion
существует тег <CFQUERY>, позволяющий передавать SQL-запросы в базу данных
как для выполнения определенных действий, так и для извлечения результирующих
данных. Это не единственный тег в ColdFusion, предназначенный для работы с базами
данных. Однако тег <CFQUERY> можно определить как основной и требующий
отдельного внимания.
Синтаксис:
<CFQUERY
NAME = "query_name"
DATASOURCE = "ds_riame" DBTYPE = "type" OBSERVER = "dbms"
DBNAME = "database name" CONNECTSTRING = "connection string"
USERNAME = "username" PASSWORD = "password"
MAXROWS = "number" BLOCKFACTOR = "blocksize"
TIMEOUT = "milliseconds" CACHEDAFTER = "date"
CACHEDWITHIN
= "timespan" PROVIDER = "COMProvider"
PROVIDERDSN
= "datasource" DEBUG = "Yes | No"> SQL-предложения
</CFQUERY>
В табл. 11.1
представлено описание атрибутов тега <CF'QUERY>.
Таблица
11.1. Описание атрибутов тега <CFQUER Y>
Атрибут |
Описание |
||
NAME
DATASOURCE |
Имя запроса.
Обязательный атрибут. Должно начинаться с буквы, может включать буквы,
цифры и символ подчеркивания. Пробелы недопустимы Источник данных,
к которому обращен запрос. Обязательный атрибут для всех значений
атрибутов DBTYPE кроме DBTYPE="query"
И DBTYPE="dynamic" |
||
DBTYPE OBSERVER DBNAME
CONNECTSTRING |
Тип драйвера
базы данных. Необязательный атрибут. Возможные значения:
Имя сервера
БД. Необязательный атрибут. Применяется для собственных драйверов
и SQLOLEDB. При определении OBSERVER игнорируется установка источника
данных Имя БД (только
для Sybase System 11 и SQLOLEDB). Необязательный атрибут. При определении
DBNAME игнорируется БД по умолчанию, установленная в источнике данных Строка соединения
для отправления к ODBC-серверу. Требуется для DBTYPE -"dynamic",
необязательный атрибут для всех других типов. При соединении с источником
данных, определенным в "ColdFusion Administrator", можно
использовать этот атрибут, чтобы определить дополнительные детали
соединения ИЛИ переопределить информацию о соединении. Если вы динамически
соединяетесь с источником данных, указанным в атрибуте DATASOURCE,
определяя DBTYPE="dynamic", строка соединения должна определить
все требуемые параметры соединения ODBC |
||
Атрибут |
Описание |
||
USERNAME |
Имя пользователя.
Необязательный атрибут. При определении данного атрибута значение
USERNAME, указанное в источнике данных, игнорируется |
||
PASSWORD |
Пароль пользователя.
Необязательный атрибут. При определении данного атрибута значение
PASSWORD, указанное в источнике данных, игнорируется |
||
MAXROWS |
Определяет максимальное
количество записей для возвращаемого результата. Необязательный атрибут.
Может принимать значение —1, что позволяет не ограничивать возвращаемое
количество записей |
||
BLOCKFACTOR |
Максимальное
количество записей для одновременной выборки (fetch) с сервера. Необязательный
атрибут. Диапазон от 1 (по умолчанию) до 100. Этот атрибут применяется
для собственных драйверов Oracle и ODBC-драйверов. Некоторые драйверы
ODBC могут динамически уменьшать размер данного блока |
||
TIMEOUT |
Максимальное
время ожидания выполнения запроса в миллисекундах. Необязательный
атрибут. TIMEOUT поддерживается SQL Server 6.x и более поздними
версиями. Минимально и максимально допустимые значения зависят от
драйвера |
||
CACHEDAFTER |
Значение даты.
Необязательный атрибут. Позволяет использовать кэширование данных
запроса, если дата запроса оригинала принимает более позднее значение
даты, установленной с помощью CACHEDAFTER. Эффективно только если
в "ColdFusion Administrator" разрешено кэширование запросов.
Чтобы применять кэширование данных, текущий запрос должен использовать
то же самое SQL-предложение, источник данных, имя запроса, имя пользователя,
пароль и тип драйвера |
||
CACHEDWITHIN |
Промежуток,
использующий функцию ColdFusion CreateTimeSpan. Необязательный атрибут.
Позволяет применять кэширование данных запроса, если дата запроса
оригинала 'попадает в промежуток времени, который определяется функцией
CreateTimeSpan. Эффективно, только если в "ColdFusion Administrator"
разрешено кэширование запросов. Чтобы использовать кэширование данных,
текущий запрос должен содержать то же самое SQL-предложение, источник
данных, имя запроса, имя пользователя, пароль и тип драйвера |
||
PROVIDER |
СОМ-поставщик.
Необязательный атрибут. Только для OLE DB |
||
PROVIDERDSN |
Имя поставщика
данных. Необязательный атрибут. Только для OLEDB |
||
DEBUG |
Используется
для отладки запроса. Необязательный атрибут. Возможные значения: • Yes —да; • No — нет (по
умолчанию) |
||
Атрибут |
Описание |
||
USERNAME |
Имя пользователя.
Необязательный атрибут. При определении данного атрибута значение
USERNAME, указанное в источнике данных, игнорируется |
||
PASSWORD |
Пароль пользователя.
Необязательный атрибут. При определении данного атрибута значение
PASSWORD, указанное в источнике данных, игнорируется |
||
MAXROWS |
Определяет максимальное
количество записей для возвращаемого результата. Необязательный атрибут.
Может принимать значение -1, что позволяет не ограничивать возвращаемое
количество записей |
||
BLOCKFACTOR |
Максимальное
количество записей для одновременной выборки (fetch) с сервера. Необязательный
атрибут. Диапазон от 1 (по умолчанию) до 100. Этот атрибут применяется
для собственных драйверов Oracle и ODBC-драйверов. Некоторые драйверы
ODBC могут динамически уменьшать размер данного блока |
||
TIMEOUT |
Максимальное
время ожидания выполнения запроса в миллисекундах. Необязательный
атрибут. TIMEOUT поддерживается SQL Server 6.x и более поздними версиями.
Минимально и максимально допустимые значения зависят от драйвера |
||
CACHE DAFTER |
Значение даты.
Необязательный атрибут. Позволяет использовать кэширование данных
запроса, если дата запроса оригинала принимает более позднее значение
даты, установленной с помощью CACHEDAFTER. Эффективно только если
в "ColdFusion Administrator" разрешено кэширование запросов.
Чтобы применять кэширование данных, текущий запрос должен использовать
то же самое SQL-предложение, источник данных, имя запроса, имя пользователя,
пароль и тип драйвера |
||
CACHE DWITHIN |
Промежуток,
использующий функцию ColdFusion CreateTimeSpan. Необязательный атрибут.
Позволяет применять кэширование данных запроса, если дата запроса
оригинала попадает в промежуток времени, который определяется функцией
CreateTimeSpan. Эффективно, только если в "ColdFusion Administrator"
разрешено кэширование запросов. Чтобы использовать кэширование данных,
текущий запрос должен содержать то же самое SQL-предложение, источник
данных, имя запроса, имя пользователя, пароль и тип драйвера |
||
PROVIDER |
СОМ-поставщик.
Необязательный атрибут. Только для OLE DB |
||
PROVIDERDSN |
Имя поставщика
данных. Необязательный атрибут. Только для OLEDB |
||
DEBUG |
Используется
для отладки запроса. Необязательный атрибут. Возможные значения: • Yes —да; • No - нет (по
умолчанию) |
||
Тег <CFQUERY>
возвращает сведения о запросе. В частности конструкция CFQUERY.ExecutionTime
возвращает измеряемое в миллисекундах время, которое требуется запросу для его
выполнения.
Так же тег
<CFQUERY> создает объект запроса, обеспечивающий доступ к вспомогательной
информации, посредством следующих переменных:
Прежде чем
демонстрировать какие-либо примеры, рассмотрим синтаксис SQL-команды SELECT,
позволяющей извлекать данные из одной или нескольких таблиц базы данных.
Предложение
SELECT задает поля, константы и выражения, которые будут отображены в результатах
запроса.
Синтаксис:
SELECT [ALL
| DISTINCT]
select_item [AS coluntn_name]
[, select_item [AS column_name] ...]
FROM table_name [, table_name ...]
[WHERE join_condition
[AND join_condition ...]
[AND I OR filter_condition [AND | OR filter_condition ...]]]
[GROUP BY group_column [, group_column ...]]
[HAVING filter_condition] [UNION [ALL] SELECTcommand]
[ORDER BY order_item [ASC | DESC]
[, order_item
[ASC | DESC] ...]]
Параметры:
Опция ALL
по умолчанию отображает в результатах запроса все строки.
Опция DISTINCT
исключает из результатов запроса повторяющиеся строки. Ее указание в предложении
SELECT допустимо только один раз.
Значение
select_item задает элемент, который следует включить в столбец результатов запроса.
Выбираемые элементы могут быть следующими:
Каждый элемент
select_item генерирует один столбец результатов запроса. Если несколько элементов
имеют одинаковые имена, укажите перед именем элемента псевдоним таблицы с точкой,
чтобы столбцы не повторялись.
Замечание
Применение
пользовательских функций в предложении SELECT обладает очевидными плюсами, но,
тем не менее, необходимо иметь в виду, что скорость выполнения операций с помощью
конструкции SELECT может быть ограничена скоростью выполнения этих пользовательских
функций.
Для выбираемого
элемента SELECT, являющегося полем или выражением с участием поля, могут быть
использованы следующие функции полей:
Задает заголовок
столбца в выводе запроса. Это предложение полезно в случае, когда select_item
является выражением или содержит функцию поля, а вы хотите назначить столбцу
осмысленное имя. Имя column_name может быть выражением, но не может содержать
символы, запрещенные в именах табличных полей.
Задает список
таблиц, которые содержат данные, извлекаемые по запросу.
Указывает,
что в результат запроса включаются лишь некоторые записи. Предложение WHERE
требуется при извлечении данных из нескольких таблиц.
Условие join_condition
задает поля, которые связывают таблицы, указанные в предложении FROM. Если в
запрос включено более одной таблицы, то для каждой таблицы, кроме первой, необходимо
определить условие объединения.
Чтобы связать
несколько условий объединения, воспользуйтесь оператором AND. Каждое условие
объединения имеет следующий формат:
field_namel
comparison field_name2
где field_namel — имя поля одной таблицы ;
field_name2
— имя поля другой таблицы, a comparison представляет один из операторов,
представленных в табл. 11.2.
Таблица
11.2. Операторы условия объединения
Оператор |
Тип сравнения |
||
= |
Равно |
||
== |
В точности равно |
||
LIKE |
Похоже |
||
< >, !
= |
Не равно |
||
> |
Больше |
||
> = |
Больше или равно |
||
< |
Меньше |
||
< = |
Меньше или равно |
||
Группирует
строки в запросе, исходя из значений в одном или нескольких столбцах. В качестве
group_column можно задать имя обычного поля таблицы, имя поля, содержащего функцию
поля SQL, или числовое выражение, указывающее позицию данного столбца в таблице
результатов (самый левый столбец имеет номер 1).
Задает условие
фильтра, которому должны удовлетворять группы, чтобы быть включенными в результаты
запроса. Предложение HAVING следует использовать вместе с конструкцией GROUP
BY. Оно может включать сколько угодно условий фильтра, связанных операторами
AND и ок. Также можно использовать оператор NOT, изменяющий значение логического
выражения на противоположное.
Условие f
ilter_condition не может содержать подзапрос.
Предложение
HAVING без предложения GROUP BY действует, как предложение WHERE.
Комбинирует
окончательные результаты одного запроса SELECT с окончательными результатами
другого запроса SELECT. По умолчанию предложение
UNION проверяет скомбинированные результаты и удаляет повторяющиеся строки.
Чтобы скомбинировать несколько предложений UNION, используйте скобки.
Если задана
опция ALL, предложение UNION не будет удалять из комбинированных результатов
повторяющиеся строки.
Предложения
UNION подчиняются следующим правилам:
Предложение
UNION также можно использовать для моделирования внешнего объединения (outer
join).
Когда вы
объединяете две таблицы в одном запросе, в вывод включаются только записи с
совпадающими значениями в объединяемых полях. Если у некоторой записи родительской
таблицы нет соответствующей ей записи в дочерней таблице, эта родительская запись
не включается в вывод. Внешнее объединение позволяет включить в вывод все записи
родительской таблицы вместе с совпадающими записями из дочерней таблицы.
Сортирует
результаты запроса по содержимому одного или нескольких столбцов. Каждый аргумент
order_item должен соответствовать некоторому столбцу результатов и может представлять
собой один из следующих элементов:
Опция ASC
задает возрастающий порядок сортировки результатов запроса, в соответствии с
элементом (или элементами) order_item, и используется по умолчанию в предложении
ORDER BY.
Опция DESC
задает убывающий порядок сортировки результатов запроса.
Если вы не
задали порядок результатов запроса с помощью предложения ORDER BY, они останутся
неупорядоченными.
Предположим,
нам необходимо организовать предварительный запрос для открытия сеанса по заказу
билетов на существующие круизы.
Напомним,
в девятом пункте бизнес-правил (см. разд. "Бизнес-правила" гл.
5) мы определили, что при регистрации электронный адрес в то же время является
входным именем пользователя (Login ID). В этом случае требуется создать диалоговую
форму для ввода электронного адреса и пароля потенциального путешественника
для последующей проверки наличия регистрации данного покупателя. Исходя из структуры
базы данных CRUISE, непосредственно сам запрос будет выглядеть следующим образом:
<CFQUERY
NAME="VerificatioriTra" DATASOURCE="lapplication.dsni">
SELECT key_tra, FirstName_tra, LastName_tra, EMail_tra, 'Gender_tra
FROM Traveler
WHERE EMail_tra = '#Form.EMail#'
AND Password_tra
= '#Form.Password#' </CFQUERY>
где Form.EMail
и Form. Password — переменные формы, предварительно заполненные пользователем.
Следующим
этапом мы можем создать переменные сессии, позволяющие в дальнейшем определять
пользователя на протяжении всей текущей сессии и не затруднять его повторном
заполнением диалоговой формы. Этот код выглядит так:
<CFIF VerificationTra.RecordCount
eq 1> <CFSET Session.login = "true">
<CFSET Session.traveler.id = #VerificationTra.key_tra#>
<CFSET Session.traveler.gender =#VerificationTra.Gender_tra#>
<CFSET Session.traveler.name
= #VerificationTra.FirstName_traf & " " &
#VerificationTra.LastName_tral>
<CFINCLUDE
TEMPLATE = "Welcome.cfm">
<CFELSE>
<!--- Неудачная
аутентификация (Authenticate failure) --->
<META HTTP-EQUIV="Refresh"
CONTENT="0;URL=BuyTickets.cfm?error=l">
</CFIF>
Смысл представленного
кода заключается в определении количества записей, полученных в результате запроса,
и т. к. разные покупатели не могут иметь один и тот же электронный адрес, то
и количество записей данного запроса может равняться 1 при удачной проверке
и 0 при неудачной проверке. В данном коде мы использовали встроенную переменную
запроса RecordCount.
Далее продемонстрируем
полный код страницы BuyTickefts.cfm, позволяющей решить поставленную перед нами
задачу (листинг 11.1).
Листинг 11.1. Код страницы BuyTickets.cfm
<HTML>
<HEAD>
<CFINCLUDE
TEMPLATE = "MyHEAD.cfm">
<link rel="STYLESHEET" type="text/css" href="main.ess">
<script type="text/javascript"
language="JavaScript"
src="main.js"></script>
<style type="text/css">
<! —
|Logln { position:absolute;
left:20; top:140; width:200;
height:100;
margin:0;z-index:0;} —> </style>
<script language="
JavaScript">
if (ie) {document
.write ( '<link rel="stylesheet" type="text/css"
'href="main_ie . ess" title="master"> ' ) ; }
function SendPassword()
{
if (ie) var
EMail = document. forml.EMail. value;
else var EMail
=
document . layers
[ 'Login' ] .document. forml.EMail. value/-
if (EMail=="")
{
alert ('Enter
please E-mail'); } else {
location . href
="Sendpassword . cfm?EMail_tra="+EMail ;
}
</script>
</HEAD> <BODY onload="init (1) "
bgcolor="<CFOUTPUT>#application.BGColorPage#</CFOUTPUT>"
text="Black" alink="#107098" link="#OC!C47"
vlink="#003366"> <CFINCLUDE TEMPLATE = "BasicBlock. cfm">
<CFIF isDefined(
"Session. traveler. id") >
<! --- The traveler is already determined --- >
<CFINCLUDE
TEMPLATE = "Welcome. cfm"> <CFELSE>
<CFIF isDefined( "Form. EMail") AND isDef ined( "Form. Password" )>
<! --- Проверка путешественника (Verification traveler) --- >
<CFQUERY NAME="VerificationTra" DATASOURCE="#application.dsn#">
SELECT Key_tra,
FirstName_tra, LastName_tra, EMail_tra,
Gender_tra FROM
Traveler WHERE EMail_tra = ' #Form.EMaili '
AND Password_tra
= '# Form. Pass wordtf ' </CFQUERY>
<CFIF VerificationTra.RecordCount eq 1>
<CFSET Session.
login = "true">
<CFSET Session. traveler. id = #Verif icationTra. key_tra#>
<CFSET Session. traveler. gender = #Verif icationTra. Gender_tra#>
<CFSET Session.
traveler. name = IVerif icationTra. FirstName_tral & " " &
#Verif icationTra. LastName tra#>
<CFINCLUDE TEMPLATE = "Welcome.cfm">
<CFELSE>
<!--- Неудачная
аутентификация (Authenticate failure) --->
<META HTTP-EQUIV="Refresh"
CONTENT="0;
URL=BuyTickets.cfm?error=l"> </CFIF>
<CFELSE>
<CFIF isDefined("Error")>
<CFSET msgError="#application.msgErrorLogini">
<CFELSE>
<CFSET msgError="">
</CFIF>
<DIV id="LogIn">
<FORM action='BuyTickets.cfm' method='post' name='forml'>
<TABLE border='0'
cellspacing='0' cellpadding='0'> <TR>
<TRXTD colspan="2"
bgcolor="#22c6d" height=l></TD>
<TD colspan="2" height=l></TD></TR>
<TD class="menleft">
<IMG name="bulll"
src="bullet2.gif" width="20"
height="20" border="0"></TD>
<TD width="55" class="menleft">Log In</TD>
<TD bgcolor="#122c6d"></TD> <TD class="menleft">
<a href="SignUp.cfm"
onMouseOver="mouse_over_bull{'bul!2', 'Login');
window.status='Sign Up';
return true" onMouseOut="mouse_out_bull('bul!2', 'Login');
window.status='';
return true">
<IMG name="bul12"
src="bullet.gif" width="20" height="20"
border="0"></a></TD>
<TD width="82"><a href="SignUp. cfm"
onMouseOver="mouse_over_bull('bul12', 'Login');"
onMouseOut="mouse_out_bull('bul12', 'Login');"
class="menleft">Sign
Up</a></TD>
<TRXTD colspan="2"
height=l></TD>
<TD colspan="4"
bgcolor="#122c6d" height=l></TD></TR>
</TR> </TABLE>
<TABLE border='0'
cellspacing='2' cellpadding='0'>
<TR><TD
colspan="2" align="center" class="txtError">
<CFOUTPUT>#msgError#</CFOUTPUT></td></tr>
<TR><TD width="100" align="right" class="txtForm1"> E-Mail</td>
<td class="note"> <input name='EMail' size=' 16'></td></tr> ;
<TR><TD align="right" class="txtForml"> Password</tdxtd class="note">
<input type='
password' name=' Password'
size=' 16'></TD></TR>
<TR><TD
align="right">
<input type=' submit' value='Send'></TD><TD>
<input type=' reset' value= ' Clear '></TD></TR>
<TR><TD colspan="2" align="left" class="txtForml">
Forgot your
pas sword? <br> <a href=" javascript : SendPassword ( ) ; "
onMouseOver="window.
status='Have it emailed to you'; return true"
onMouseOut="window.
status=' ' ; return true"> Have it emailed to you</a></TD></TR>
</TABLE> </FORM>
</DIV>
</CFIF> </CFIF> </BODY> </HTML>
Как видно
из примера, в результате удачного открытия сеанса мы включаем с помощью тега
<CFINCLUDE> страницу Welcome. cfm. В листинге 11.2 продемонстрируем код
страницы Welcome. cfm.
Листинг
11.2. Код страницы Welcome.cfm
<CFIF ISession.
traveler. gendertt eq "1">
<CFSET Appeal="Ms.
"> <CFELSE>
<CFSET Appeal="Mr.">
</CFIF>
<CFOUTPUT>
<div id="LogIn">
<p class="smalltxt">Welcome<br>Dear
#Appeal#
<a href="UpdateTra.cfm">#Session.traveler.name#</a>
, thank you
for your interest in My-Cruises Line.</p>
</div>
</CFOUTPUT>
<!--- The
information block on cruises --->
<!---...--->
В нашем примере
именно на странице Welcome.cfm подразумевается размещение информации.о текущих
круизах. Обращаем ваше внимание на то, что в данном примере встречается ссылка
на страницу .UpdateTra.cfm, предназначенную для обновления данных о пользователе
текущей сессии. Однако об этом чуть позже.
Отметим лишь,
что для удачного открытия сессии необходимо наличие в базе данных сведений о
зарегистрированных пользователях. Далее мы продемонстрируем пример добавления
данных с помощью ColdFusion.
Для добавления
данных в ColdFusion можно прибегнуть к нескольким способам, например, указать
команду внутри уже описанного нами тега <CFQUERY>, применить тэг <CFINSERT>
или тэг <CFGRID>, частично используемого
в рамках тега <CFFORM>. И если о последнем способе мы поговорим в следующей
главе, то первые два варианта рассмотрим прямо сейчас.
Прежде чем
привести пример добавления данных, рассмотри синтаксис SQL-команды INSERT.
Синтаксис:
INSERT INTO table_name [(fname1 [, fname2, ...])]
VALUES (expressionl
[, expression2, ...])
Параметры:
Задает имя
таблицы, к которой добавляется новая запись.
Определяет
имена полей новой записи, в которые вставляются значения.
Задает значения
полей, вставляемые в новую запись. Если имена полей опущены, нужно указывать
значения полей в порядке, определяемом структурой таблицы.
Допустим,
нам необходимо организовать регистрацию потенциальных покупателей билетов на
существующие круизы.
В этом случае
требуется создать диалоговую форму для ввода необходимых данных для последующего
их добавления в базу данных CRUISE. Тогда запрос в ColdFusion будет выглядеть
следующим образом:
<CFSET Birthday = iDateFormat(#Form.Birthday#, "yyyy-mm-dd")#>
<CFQUERY NAME="AddTraveler" DATASOURCE="#application.dsn#">
INSERT INTO
Traveler(EMail_tra, FirstName_tra,
LastName_tra, Middlelnitial_tra, Password_tra, Birthday_tra,
PhoneNum_tra, Gender_tra) VALUES('#Form.EMail#',
'#Form.FirstName#',
'#Form.LastName#', '#Form.MiddleInitial#', '#Form.Password#',
'#Birthday#',
'#Form.PhoneNum#', #Form.Gender#) </CFQUERY>
Здесь в предложении
VALUES перечислены переменные формы, предварительно заполненные пользователем.
Следует отметить,
что мы используем БД Sybase, где формат даты по умолчанию представляется как
"yyyy-mm-dd", в свою очередь при вводе данных пользователю предлагается
вводить свой день рождения с маской "dd-mm-уууу". Поэтому для приведения
формата даты к общему знаменателю используется существующая ДЛЯ ЭТИХ целей функция
DateFormat.
Далее будем
действовать по аналогии с примером открытия сессии, рассмотренным чуть ранее,
где создавали переменные сессии, позволяющие в дальнейшем идентифицировать пользователя
на протяжении всей текущей сессии и не затруднять его повторным заполнением
диалоговой формы. Этот код выглядит так:
<CFQUERY
NAME="TravelerExtKey" DATASOURCE="#application.dsn#">
SELECT key_tra
FROM Traveler
WHERE EMail_tra='#Form.EMail#' </CFQUERY>
<CFOUTPUT
QUERY="TravelerExtKey">
<CFSET Session.login
= "true">
<CFSET Session.traveler.id
= #TravelerExtKey.key_tra#>
<CFSET Session.traveler.gender
= #Form.Gendert>
<CFSET Session.traveler.name
= #Form.FirstNamel & " " &
#Form.LastName#>
</CFOUTPUT>
Как видно
из примера, прежде чем определить переменную идентификатора пользователя, нам
пришлось создать дополнительный запрос на выборку по полю key_tra, т. к. в базе
данных CRUISE все уникальные ключи присваиваются автоматически. И только с помощью
обращения к уже добавленной записи мы определяем этот уникальный ключ.
В разд.
"Проверка переменных" гл. 9 мы уже рассматривали похожий пример
по регистрации пользователей без применения базы данных. Здесь же помимо добавления
блоков по работе с базой данных мы также несколько изменили код в соответствии
с требованием проекта "My-Line Cruises".
Далее продемонстрируем
полный код страницы SignUp.cfm, позволяющей решить поставленную перед нами задачу
(листинг 11.3).
Листинг
11.3. Код страницы SignUp.cfm
<HTML>
<HEAD>
<CFINCLUDE
TEMPLATE = "MyHEAD.cfm">
<link rel="STYLESHEET"
type="text/css" href="main.ess">
<script type="text/javascript"
language="JavaScript"
src="main. js"></script> <style type="text/css">
<! — #SignUp
{ position:absolute; left:20; top:140; width:200;
height:100;
margin:0;z-index:0;} —> </style>
<script language="JavaScript">
if (ie) {document.write('<link
rel="stylesheet" type="text/css"
href="main_ie.ess" title="master">');} </script> </HEAD>
<BODY onload="init(1)"
bgcolor="<CFOUTPUT>#application.BGColorPage#
</CFOUTPUT>" text="Black" alink="#107098" link="#iOC1C47" vlink="#003366">
<CFINCLUDE
TEMPLATE = "BasicBlock.cfm"> <CFIF isDefined("Session.traveler.id")>
<META HTTP-EQUIV="Refresh" CONTENT="0;URL=BuyTickets.cfm">
<CFELSE>
<CFIF isDefined("Form.EMail")> <CFSET DIsuccessful = 1>
<CFSET msgError
= "Warning Error!">
<CFIF Len(Form.EMail) le 5 and Form.EMail does not contain "@">
<CFSET msgError = msgError & "<br>" & #application.msgErrorl#>
<CFSET DIsuccessful =. 0> </CFIF>
<CFIF Len(Form.Password)
le 4>
<CFSET msgError = msgError & "<br>" & lapplication.msgError2#>
<CFSET DIsuccessful = 0> </CFIF>
<CFIF IsNumeric(Form.Password)>
<CFSET msgError = msgError & "<br>" & fapplication.msgError3t>
<CFSET DIsuccessful = 0> </CFIF>
<CFIF Form.Password
not equal Form.Confirm>
<CFSET msgError = msgError & "<br>" &#application.msgError4#>
<CFSET DIsuccessful = 0> </CFIF>
<CFIF Len(Form.FirstName)
le 0>
<CFSET msgError = msgError & "<br>" & lapplication.msgError5#>
<CFSET DIsuccessful = 0> </CFIF>
<CFIF Len(Form.LastName)
le 0>
<CFSET msgError = msgError & "<br>" & #application.msgError6t>
<CFSET DIsuccessful
= 0> </CFIF>
<CFIF not
IsDate(Form.Birthday) and Len(Form.Birthday)gt 0>
<CFSET msgError = msgError & "<br>" & lapplication.msgError7#>
<CFSET DIsuccessful
= 0> </CFIF>
<CFIF YesNoFormat(DIsuccessful)
equal "No"> <!--- Errors -
<CFSET email = #Form.EMail#>
<CFSET fname = #Form.FirstName#>
<CFSET Iname = #Form.LastName#>
<CFSET middle = #Form.MiddleInitial#>
<CFSET bday = #Form.Birthday#>
<CFSET phonen
= ttForm.PhoneNum#> <CFELSE>
<!--- Проверка
путешественника (Verification traveler) --->
<CFQUERY
NAME="VerificationSU" DATASOURCE="#application.dsnl">
SELECT key_tra FROM Traveler
WHERE EMai1_tra = 'tForm.EMaill' </CFQUERY>
<CFIF VerificationSU.RecordCount
eq 1>
<!--- The
record with this EMail address already exists! --->
<CFELSE>
<!--- Добавление
записи (Add record) --->
<CFSET Birthday
= IDateFormat(tForm.Birthday#,
"yyyy-mm-dd")tt>
<CFQUERY
NAME="AddTraveler" DATASOURCE="#application.dsn#"> INSERT
INTO Traveler(EMail_tra, FirstName_tra,
LastName_tra, Middlelnitial_tra, Password_tra, Birthday_tra,
PhoneNum_tra, Gender_tra) VALUES('#Form.EMail#',
'#Form.FirstName#',
1tForm.LastName#',
'#Form.MiddleInitial#', 1#Form.Password!', '#Birthday#', '#Form.PhoneNumi',
#Form.Gender#) </CFQUERY>
<!--- Извлечение
по ключу (Extraction of a key) --->
<CFQUERY
NAME="TravelerExtKey"
DATASOURCE="ttapplication.dsn#">
SELECT key_tra
FROM Traveler
WHERE EMail_tra='#Form.EMail#' </CFQUERY>
<CFOUTPUT
QUERY="TravelerExtKey"> <CFSET Session.login = "true">
<CFSET Session.traveler.id = #TravelerExtKey.key_tra#>
<CFSET Session.traveler.gender = #Form.Gender#>
<CFSET Session.traveler.name
= #Form.FirstName# & " " &
#Form.LastName#>
</CFOUTPUT> </CFIF>
<META HTTP-EQUIV="Refresh" CONTENT="0;URL=BuyTickets . cfm">
<CFEXIT>
</CFIF> <CFELSE>
<CFSET email = ""> <CFSET fname = "">
<CFSET Iname = ""> <CFSET middle = "">
<CFSET bday = ""> <CFSET phonen = "">
<CFSET msgError = ""> </CFIF>
<DIV id="SignUp">
<FORM action='SignUp.cfm' method='post' name=' form1' >
<TABLE border='0'
cellspacing='0' cellpadding='0'> <TR>
<TR><TD
colspan="2" height=l></TD>
<TD colspan="4" bgcolor="#122c6d" height=l></TD></TR>
<TD class="menleft"><a
href="BuyTickets.cfm"
onMouseOver="mouse_over_bull('bu112',
'SignUp'); window.status='Sign Up'; return true"
onMouseOut="mouse_out_bull('bul!2', 'SignUp');
window.status=''; return true">
<IMG name="bull2"
src="bullet.gif" width="20"
height="20" border="0"></a></TD>
<TD width="55"><a
href="BuyTickets . cfm"
onMouseOver="mouse_over_bull('bul12', 'SignUp');"
onMouseOut="mouse_out_bull('bul12', 'SignUp');"
class="menleft">Log
In</a></TD>
<TD bgcolor="tl22c6d"></TD>
<TD class="menleft">
<IMG name="bulll"
src="bullet2.gif" width="20"
height="20" border="0"></TD>
<TD width="82" class="menleft">Sign Up</TD>
<TR><TD
colspan="2" bgcolor="#122c6d" height=l>
</TD><TD colspan="2" height=l></TD></TR> </TR>
</TABLE>
<TABLE width="300" border="0" cellspacing="2" cellpadding="0">
<TR><TD
colspan="2" align="center" class="txtError">
<CFOUTPUT>#msgError#</CFOUTPUT></TD></TR>
<TR><TD
align="right" class="txtForml">
E-Mail (Login)</tdxtd width="215" class="txtForm1">
<input name='EMail'
size='16'
value="<CFOUTPUT>#email#</CFOUTPUT>"> *
</TD></TR> *
<TR><TD align="right" class="txtForml"> Password</td>
<td class="txtForml">
<input type='password'
name='Password'
size="16' > *</TD></TR>
<TR><TD align="right" class="txtForml"> Confirm</td>
<td class="txtForml">
<input type='password' name='Confirm'
size='16'> *</TD></TR>
<TR><TD
align="right" class="txtForml">
First Name</td><td class="txtForml">
<input name='FirstName'
size='16'
value="<CFOUTPUT>#fname#</CFOUTPUT>"> * </TD></TR>
<TR><TD
align="right" class="txtForml">
Last Name</td><td
class="txtForml"> <input name='LastName' size='16'
value="<CFOUTPUT>#lnamel</CFOUTPUT>"> *
</TD></TR>
<TR><TD align="right" class="txtForml"> Middle Initial</td>
<td> <input
name='MiddleInitial' size='l'
value="<CFOUTPUT>#middle#</CFOUTPUT>"></TD></TR>
<TR><TD align="right" class="txtForml"> Birthday</td>
<td class="txtForml">
<input name=' Birthday' size='10'
value="<CFOUTPUT>#bday#</CFOUTPUT>">
dd-mm-yyyy</TD></TR>
<TR><TD align="right" class="txtForml"> Phone Num.</td>
<td> <input
name= ' PhoneNum ' size='10'
value="<CFOUTPUT>fphonen#</CFOUTPUT>"></TD></TR>
<TR><TD align="right" class="txtForml"> Gender</TD>
<TD> <select name= ' Gender '>
<option value="0">male <option value="l">female </select></TD></TR>
<TR><TD
align=" right ">
<input type= ' submit ' value=' Add '></TD><TD>
<input type='
reset' value= ' Clear '></TD></TR> </TABLE> </FORM>
</CFIF>
</BODY> </HTML>
Отметим то,
что сообщения об ошибках определены в конфигурационном файле Application.cfm
так, как это показано в разд. "Пример файла Application. cf т"
гл. 10.
Также для
добавления данных в ColdFusion можно использовать тег <CFINSERT>, о чем
и пойдет речь в следующем! разделе с предварительным описанием этого тега.
Синтаксис:
<CFINSERT DATASOURCE = "ds_name"
DBTYPE = "type"
DBSERVER = "dbms"
DBNAME = "database name"
TABLENAME =
"tbl name"
CONNECTSTRING
= "connection string"
TABLEOWNER =
"owner"
TABLEQUALIFIER
= "tbl_qualifier"
USERNAME = "username"
PASSWORD = "password"
PROVIDER = "COMProvider"
PROVIDERDSN
= "datasource"
FORMFIELDS =
"formfield1, formfield2, . . . ">
В табл. 11.3
представлено описание атрибутов тега <CFINSERT>.
Таблица
11.3. Описание атрибутов тега <CFINSERT>
Атрибут |
Описание |
||
DATASOURCE DBTYPE |
Источник данных,
к которому обращен запрос. Обязательный атрибут для всех DBTYPE кроме
DBTYPE="query" и DBTYPE=" dynamic" Тип драйвера
базы данных. Необязательный атрибут. Возможные значения:
|
||
Атрибут |
Описание |
||
OBSERVER |
Имя сервера
БД. Необязательный атрибут. Применяется для собственных драйверов
и SQL OLEDB. При определении DBSERVER игнорируется установка источника
данных |
||
DBNAME |
Имя БД (только
для Sybase System 11 и SQL OLEDB). Необязательный атрибут. При определении
DBNAME игнорируется БД по умолчанию, установленная в источнике данных |
||
TABLENAME |
Имя таблицы.
Обязательный атрибут. Обратите внимание на следующее:
|
||
CONNECTSTRING |
Строка соединения
для отправления к серверу ODBC. Требуется для DBTYPE ="dynamic".
Необязательный атрибут для всех других типов. При соединении с источником
данных, определенным в "ColdFusion Administrator", можно
использовать этот атрибут, чтобы определить дополнительные детали
соединения или переопределить информацию соединения. Если вы динамически
соединяетесь с источником данных, указанным в атрибуте DATASOURCE,
определяя DBTYPE="dynamic", строка соединения должна определить
все требуемые параметры соединения ODBC |
||
TABLEOWNER |
Владелец таблицы.
Необязательный атрибут. Может применяться для источников данных, поддерживающих
собственность (ownership) на таблицу (например, SQL Server, Oracle
и Sybase SQL Anywhere) |
||
TABLEQUALIFLER |
Описатель таблицы.
Необязательный атрибут. Может использоваться для источников данных,
поддерживающих описатель таблиц (qualifiers). Для SQL Server и Oracle
обращается к имени базы данных, которая содержит таблицу. Для dBase-драйверов
происходит обращение к каталогу, где размещаются dbf-файлы |
||
USERNAME |
Имя пользователя.
Необязательный атрибут. При определении данного атрибута значение
USERNAME, указанное в источнике данных, игнорируется |
||
PASSWORD |
Пароль пользователя.
Необязательный атрибут. При определении данного атрибута значение
PASSWORD, указанное в источнике данных, игнорируется |
||
PROVIDERDSN | Имя поставщика данных. Необязательный атрибут. Только для OLEDB | ||
FORMFIELDS | Список полей, разделенных запятыми. Необязательный атрибут. Если этот атрибут не определен, то все поля формы участвуют в операции добавления | ||
PROVIDER |
СОМ-поставщик.
Необязательный атрибут. Только для OLE DB |
||
Чтобы демонстрировать
использование тега <CFINSERT>, предназначенного для добавления записей
в базу данных, рассмотрим пример,, позволяющий регистрировать новые экскурсионные
поездки и круизы.
Решим данную
задачу по аналогии с предыдущим примером: создадим диалоговую форму, предназначенную
для ввода необходимых данных с целью их последующего добавления в базу данных
CRUISE, а именно — в таблицу TOUR. Прежде чем представить полный код страницы,
продемонстрируем отрывок этого кода, где, собственно говоря, и происходит добавление
новых значений:
<!--- Проверка
тура (Verification tour) --->
<CFQUERY NAME="VerificationNewTour" DATASOURCE="#application.dsn#">
SELECT key_tou
FROM Tour WHERE Name__tou='IForm.Name_toutt' </CFQUERY>
<CFIF VerificationNewTour.RecordCount
eq 1>
<!--- The
record with this Name tour already exists! --->
<CFELSE>
<!--- Добавление
записи (Add record) --->
<CFINSERT
DATASOURCE = "#application.dsn#" TABLENAME = "Tour"
FORMFIELDS = "Name_tou,PointDepart_tou,NumLandingPlaces_tou, Time_tou,CostAdult_tou, CostChildren_tou, CostSenior_tou,
Photo__tou, Note_tou"> </CFIF>
<META HTTP-EQUIV="Refresh" CONTENT="0;
URL=AdminListTour.cfm">
Здесь, прежде
чем произвести добавление новой записи, создаем дополнительный запрос, позволяющий
проверить, существует ли данный круиз в текущей базе данных. И только при отсутствии
круиза совершаем добавление
введенных пользователем данных и активизируем страницу со списком всех зарегистрированных
круизов.
В листинге
11.4 представлен полный код страницы AdminNewTour.cfm, позволяющей решить сформулированную
выше задачу.
Листинг
11.4. Код страницы AdminNewTour.cfm
<HTML>
<HEAD>
<CFINCLUDE
TEMPLATE = "MyHEAD.cfm">
<link rel="STYLESHEET" type="text/css" href="main.css">
<script type="text/javascript"
language="JavaScript"
src="main. js"></script> <style type="text/css">
<! — #Tour
{ position:absolute; left:20; top:140; width:200;'height:100;
margin:0; z-index:0;}
—>
</style>
<script language="JavaScript">
if (ie) (document.write{'<link
rel="stylesheet" type="text/css"
href="main_ie.ess"
title="master">');} </script> </HEAD> <BODY onload="init(1)"
bgcolor="<CFOUTPUT>#application.BGColorPage#</CFOUTPUT>"
text="Black" alink="#107098" link="#OC1C47" vlink="#003366">
<CFINCLUDE TEMPLATE = "BasicBlock.cfm"> <CFIF isDefined("Form.Name_tou")>
<CFSET DIsuccessful = 1>
<CFSET msgError
=-"Warning Error!">
<CFIF Len(Form.Name_tou)
le 0 or Len(Fqrm.PointDepart_tou) le 0 or Len(Form.NumLandingPlaces_tou) le
0 or Len(Form.Time_tou) le 0 or Len(Form.CostAdult_tou) le 0 or Len(Form.CostChildren_tou)
le 0
or Len(Form.CostSenior_tou)
le 0> <CFSET msgError = msgError & "<br>" & "The
fields marked with
a symbol *,
should not be empty!"> <CFSET DIsuccessful = 0> </CFIF>
<CFIF YesNoFormat(DIsuccessful)
equal "No"> <!--- Ошибки (Errors) --->
<CFSET Name_tou
= #Form.Name_tou#>
<CFSET PointDepart_tou
= #Form.PointDepart_tou#>
<CFSET NumLandingPlaces_tou
= #Form.NumLandingPlaces_tou#>
<CFSET Time_tou
= #Form.Time_tou#>
<CFSET CostAdult_tou
= #Form.CostAdult_tout>
<CFSET CostChildren_tou
= iForm.CostChildren_toul>
<CFSET CostSenior_tou
= #Form.CostSenior_tou#>
<CFSET Photo_tou
= #Form.Photo_tou#>
<CFSET Note
tou = #Form.Note tou#>
<CFELSE>
<!---Verification
tour--->
<CFQUERY
NAME="VerificationNewTour"
DATASOURCE="#application.dsn#">
SELECT key_tou
FROM Tour WHERE
Name_tou = '#Form.Name_tou#' </CFQUERY> <CFIF VerificationNewTour.RecordCount
eq 1>
<!--- The
record with this Name tour already exists! --->
<CFELSE>
<!--- Добавление
записи (Add record) --->
<CFINSERT
DATASOURCE = "#application.dsn#" TABLENAME = "Tour"
FORMFIELDS
= "Name_tou,PointDepart_tou, NumLandingPlaces_tou, Time_tou,CostAdult_tou,
CostChildren_tou,CostSenior_tou, Photo_tou,Note_tou"> </CFIF>
<META HTTP-EQUIV="Refresh" CONTENT="0;URL=AdminListTour.cfm">
<CFEXIT>
</CFIF> <CFELSE>
<CFSET Name_tou = ""> <CFSET PointDepart_tou = "">
<CFSET NumLandingPlaces_tou = ""> <CFSET Time_tou = "">
<CFSET CostAd.ult_tou = ""> <CFSET CostChildren_tou = "">
<CFSET CostSenior_tou = ""> <CFSET Photo_tou = "">
<CFSET Note_tou = ""> <CFSET msgError = ""> </CFIF>
<DIV id="Tour">
<FORM action='AdminNewTour.cfm'
method='post' name='forml'>
<TABLE width="370"
border="0" cellspacing="0" cellpadding="0">
<TR>
<TR><TD
colspan="2" height=l></td>
<TD colspan="4" bgcolor="#122c6d" height=l></TD></TR>
<TD class="menleft"><a
href="AdminListTour.cfm"
onMouseOver=" mouse_over_bull('bul12', 'Tour');
window.status='List Tour1;
return true" onMouseOut="mouse_out_bull('bul12', 'Tour');
window.status=''; return true">
<img name="bu!12"
src="bullet.gif" width="20"
height="20" border="0"></a></td>
<TD width="155"xa
href="AdminListTour.cfm"
onMouseOver="
mouse_over_bull('bul12', 'Tour');" onMouseOut=" mouse_out_bull('bul12',
'Tour');"
class="menleft"> List Tour</a></TD>
<TD bgcolor="#122c6d"x/TD>
<TD class="menleft">
<img name="bulll"
src="bullet2.gif" width="20"
height="20" border="0"></TD>
<td width="215" class="menleft">New Tour</TD>
<TR><TD
colspan="2" bgcolor="#122c6d" height=l></TD>
<TD colspan="2"
height=l></TD></TR> </TR> </TABLE>
<TABLE width="390" border="0" cellspacing="2" cellpadding="0">
<TR><TD
colspan="2" align="center" class="txtError">
<CFOUTPUT>fmsgErrorl</CFOUTPUT></TD></TR>
<TR><TD
align="right" class="txtForml">
Name tour</tdxtd width="230" class="txtForml">
<input name='Name_tou'
size='30'
value="<CFOUTPUT>iName_tou#</CFOUTPOT>"> * </TD></TR>
<TR><TD
align="right" class="txtForml">
Point of departure</tdxtd class="txtForml">
<input name='PointDepart_tou'
size='30'
value="<CFOUTPUT>lPointDepart_toul
</CFOUTPUT>"> * </TD></TR>
<TR><TD
align="right" class="txtForm1">
Number of landing places</tdxtd class="txtForml">
<input name='NumLandingPlaces_tou' size='6'
value="<CFOUTPUT>lNumLandingPlaces_tou
#</CFOUTPUT>"> *
</TD></TR>
<TR><TD
align="right" class="txtForml">
Time in tour</TD><TD class="txtForml">
<input name='Time_tou'
size='2'
value="<CFOUTPUT>#Time_tou#
</CFOUTPUT>"> hours, Snbsp; * </TD></TR>
<TR><TD
align="right" class="txtForml">
Cost for adults</tdxtd class="txtForml">
<input name='CostAdult_tou'
size='6'
value="<CFOUTPUT>#CostAdult_tou#
</CFOUTPUT>"> $, Snbsp; * </TD></TR>
<TR><TD
align="right" class="txtForml">
Cost for children</td><td class="txtForml">
<input name='CostChildren_tou'
size='6'
value="<CFOUTPUT>#CostChildren_tou#
</CFOUTPUT>"> $, * </TD></TR>
<TR><TD
align="right" class="txtForml">
Cost for senior citizens</tdxtd class="txtForml">
<input name='CostSenior_tou'
size='6'
value="<CFOUTPUT>#CostSenior_tou#
</CFUUTPUT>"> $, Snbsp;* </TD></TR>
<TR><TD
align="right" class="txtForml">Photo</TD><TD>
<input name= ' Photo_tou ' type="File"
accept="image/gif
"
size= ' 23 ' value="<CFOUTPUT>#Photo_4ou#
</CFOUTPUT>"> </TD></TR>
<TR><TD
align="right" class="txtForml">Note</TD><TD>
<textarea name = "Note_tou" cols = "33" rows = "4"> . <CFOOTPUT>#Note_tou#</CFOUTPUT></textarea></TD></TR>
<TR><TD
align="right">
<input type= ' submit ' value=' Add '></TD><TD>
<input type=' reset' value= ' Clear '></TD>
</TR> </TABLE>
</FORM>
</BODY>
</HTML>
Обращаем
ваше внимание на то, что в данном примере переменные формы именуются в соответствии
с названием полей таблицы приемника данных.
Теперь, когда
мы уже имеем представление о построении запросов и добавлении данных, видимо
следует перейти к объяснению, каким образом можно выводить данные, полученные
в результате выполнения того или иного запроса.
Итак, для
вывода данных в ColdFusion можно прибегнуть к нескольким способам: либо использовать
тег <CFOUTPUT>, либо <CFTABLE> в сочетании с тегом <CFCOL>.
Впрочем, для этой цели также можно воспользоваться тегом <CFGRID>, используемым
в рамках тега <CFFORM>, но об этом поговорим в следующей главе.
Синтаксис:
<CFOUTPUT
QUERY = "query_name"
GROUP = "query_column"
GROUPCASESENSITIVE
= "Yes | No"
STARTROW = "start_row"
MAXROWS = "max_rows_output">
</CFOUTPUT>
В табл. 11.4
представлено описание атрибутов тега <CFOUTPUT>.
Таблица
11.4. Описание атрибутов тега <CFOUTPUT>
Атрибут |
Описание |
||
QUERY GROUP
GROUPCASESENSITIVE
STARTROW MAXROWS |
Имя запроса.
Необязательный атрибут. Для вывода результатов запроса внутри блока
<CFOUTPUT> Имя колонки
запроса. Необязательный атрибут. Предполагает группировку результата
запроса по указанной колонке (полю таблицы) Восприимчивость
к регистру. Необязательный атрибут. Используется для указания учета
регистра при группировке результата запроса. Возможные значения: • Yes — да (по умолчанию); • No — нет Номер записи,
с которой следует выводить полученные данные. Необязательный атрибут Максимальное
количество записей, которое следует выводить внутри блока <CFOUTPUT>.
Необязательный атрибут |
||
Мы уже неоднократно
применяли тег <CFOUTPUT> для вывода значений различных переменных, но
при этом ни разу не использовали данную конструкцию в сочетании с описанными
выше атрибутами. Здесь же мы постараемся восполнить этот пробел.
Предположим,
перед нами стоит задача вывести все круизы, зарегистрированные в базе данных.
Для решения
данной задачи предварительно следует построить запрос, например таким образом:
<CFQUERY
NAME="GetTour" DATASOURCE="#application.dsn#">
SELECT Key__tou, Name_tou, PointDepart_tou,
NumLandingPlaces__tou, Time_tou, CostAdult_tou,
CostChildren_tou,
CostSenior_tou FROM Tour </CFQUERY>
где GetTour
— имя запроса.
После чего
выведем список полученных данных с указанием имени запроса следующим образом:
<TABLE width="630" border="0" cellspacing="2" cellpadding="0">
<CFOUTPUT QUERY="GetTour">
<TR align="right">
<TD class="txtTab"
align="left"> <a href="AdminUpdateTour.cfm?key_tou=#Key_tou#">
#Name_tou#</a></TD>
<TD class="txtTab" align="left">#PointDepart_tou#</TD>
<TD class="txtTab">#NumLandingPlaces_tou#</TD>
<TD class="txtTab">#Time_tou#-hr</TD>
<TD class="txtTab">$#CostAdult_tou#</TD>
<TD class="txtTab">$#CostChildren_tou#</TD>
<TD class="txtTab">$#CostSenior_tou#</TD>
<TD class="txtTab"
align="center">
<a href="AdminNoteTour.cfm?key_tou=#Key_tou#" target="_blank">
<FONT face="Wingdings">±</FONT></a></TD>
</TR>
</CFOUTPUT>
</TABLE>
Допустим,
если бы была необходимость вывести 5 записей, начиная с шестой позиции, для
этого достаточно было бы добавить еще два атрибута:
<CFOUTPUT
QUERY="GetTour" STARTROW="6" MAXROWS="5">
На рис. 11.1
представлен список всех круизов, зарегистрированных в базе данных, в рамках
проекта "My-Line Cruises".
Рис.
11.1. Пример вывода списка круизов
Далее продемонстрируем
полный код страницы AdminListTour.cfm, позволяющей решить описанную выше задачу
(листинг 11.5).
Листинг
11.5. Код страницы AdminListTour.cfm
<HTML>
<HEAD>
<CFINCLUDE
TEMPLATE = "MyHEAD.cfm">
<link rel="STYLESHEET"
type="text/css" href="main.css">
<script type="text/javascript"
language="JavaScript"
src="main.
js"x/script> <style type="text/css"> <! —
#Tour { position:absolute;
left:20; top:140; width:200; height:100;
margin:0; z-index:0;}
—>
</style>
<script language="JavaScript">
if (ie) {document.write('<link
rel="stylesheet" type="text/css"
href="main_ie.ess" title="master">'};} </script> </HEAD>
<BODY onload="init(1)"
bgcolor="<CFOUTPUT>#application.BGColorPage#</CFOUTPUT>" text="Black" alink="#107098" link="#OC1C47" vlink="§003366">
<CFINCLUDE TEMPLATE = "BasicBlock.cfm">
<CFQUERY
NAME="GetTour" DATASOURCE="#application.dsn#">
SELECT Key_tou, Name_tou, PointDepart_tou, NumLandingPlaces_tou, Time_tou, CostAdult_tou, CostChildren_tou, CostSenior_tou FROM Tour </CFQUERY>
<DIV id="Tour">
<TABLE width="370"
border="0" cellspacing="0" cellpadding="0">
<TR>
<TR><TD
colspan="2" bgcolor="#122c6d" height=l></TD>
<TD colspan="2"
height=l></TD></TR> <TD class="menleft">
<IMG name="bulll"
src="bullet2.gif" width="20" height="20"
border="0"></TD>
<TD width="155" class="menleft">List Tour</TD>
<TD bgcolor="H22c6d"></TD> <TD class="menleft">
<a href="AdminNewTour.cfm"
onMouseOver="mouse_over_bull('bull2',
'Tour');
window.status='New
Tour'; return true"
onMouseOut="mouse_out_bull('bull2',
'Tour');
window.status='';
return true">
<IMG name="bull2"
src="bullet.gif" width="20" height="20"
border="0"></a></TD>
<TD width="215"xa href="AdminNewTour.cfm"
onMouseOver="mouse_over_bull('bul12', 'Tour');"
onMouseOut="mouse_out_bull('bul12',
'Tour');"
class="menleft">
New Tour</ax/td> <TR><TD colspan="2" height=lx/TD>
<TD colspan="4"
bgcolor="#122c6d" height=lx/TDx/TR> </TR> </TABLE>
<br>
<TABLE width="630" border="0" cellspacing="2" cellpadding="0">
<TR align="center">
<TD class="txtTitleTab" width="160" align="left">Name tour</TD>
<TD class="txtTitleTab"
width="175" align="left">
Point of departure</TD>
<TD class="txtTitleTab" width="40">Places</td>
<TD class="txtTitleTab" width="55">Time</TD>
<TD class="txtTitleTab" width="55">Adults</TD>
<TD class="txtTitleTab" width="55">Children</TD>
<TD class="txtTitleTab" width="55">Seniors</TD>
<TD class="txtTitleTab"
width="35">Note</TD> </TR>
<CFOUTPOT
QUERY="GetTour"> <TR align="right">
<TD class="txtTab"
align="left">
<a href="AdminUpdateTour
.cfm?key_tou=#Key_tou#">
#Name_tou#</a></td>
<TD class="txtTab" align="left">#PointDepart_tou#</TD>
<TD class="txtTab">#NumLandingPlaces_tou#</TD>
<TD class="txtTab">fTime_tou#-hr</TD>
<TD class="txtTab">$#CostAdult_tou#</TD>
<TD class="txtTab">$#CostChildren_touf</TD>
<TD class="txtTab">$#CostSenior_toul</TD>
<TD class="txtTab"
align="center">
<a href="AdminNoteTour
. cfm?key_tou=#Key_tout"
target="_blank">
<FONT face="Wingdings">±</FONTx/a></TD>
</TR>
</CFOUTPUT>
</TABLE>
</div>
</BODY>
</HTML>
Обращаем
ваше внимание на то, что в данном примере встречаются две ссылки: на страницу
AdminUpdateTour.cfm, предназначенную для обновления выбранной записи, и страницу
AdminNoteTour.cfm, служащую для вывода дополнительной информации по текущей
записи. Что касается обновления данных, то об этом чуть позже.
Сейчас же
рассмотрим страницу AdminNoteTour.cfm, куда, как видно из кода страницы AdmlnListTour.cfm,
передается значение поля Key_tou текущей записи. Это позволяет определить условие
запроса для вывода дополнительной информации, и т. к. значение поля Key_tou
является уникальным по определению, то и результат выборки будет включать одну
необходимую запись.
В листинге 11.6 приведен полный код страницы AdminNoteTour.cfm.
Листинг
11.6. Код страницы AdminNoteTour.cfm
<HTML>
<HEAD>
<CFINCLUDE
TEMPLATE = "MyHEAD.cfm">
<link rel="STYLESHEET"
type="text/css" href="main.css">
<script type="text/javascript"
language="JavaScript"
src="main.
js"></script> <script language="JavaScript">
if (ie) {document.write('<link
rel="stylesheet" type="text/css"
href="main_ie.ess" title="master">');)
</script> </HEAD>
<BODY bgcolor="<CFOUTPUT>#application.BGColorPage#</CFOUTPUT>"
text="Black" alink="#107098" link="#OC1C47" vlink="#003366">
<CFIF isDefined("URL.key_tou")>
<CFQUERY
NAME="GetTour" DATASOURCE="#application.dsn#"> SELECT
Name_tou, Note_tou, Photo_tou
FROM Tour WHERE Key_tou = #Url.key_tou# </CFQUERY>
<CFOUTFUT
QUERY="GetTour">
<p class="title">#Name_tou#</p>
<TABLE width="100%"
border="0" cellspacing="2" cellpadding="0">
<TR> <TD>
<CFIF Photo_tou
contains "gif">
<IMG src="#Photo_tou#"
alt="" border="0"> </CFIF> </TD>
<TD class="txt">#Note_tou#</TD>
</TR> </TABLE> </CPOUTPUT>
<CFELSE>
<script language="JavaScript">self.close();
</script>
</CFIF> </BODY> </HTML>
Отметим,
что в случае отсутствия переменной URL.key_tou страница AdminNoteTour.cfm автоматически
закрывается.
Также вывести
данные в ColdFusion можно с помощью тега <CFTABLE> в сочетании с тегом
<CFCOL>. О чем, собственно говоря, и пойдет речь в следующем разделе с
предварительным описанием тегов <CFTABLE> и <CFCOL>.
Синтаксис:
<CFTABLE
QUERY = "query_name"
MAXROWS = "maxrows_table"
COLSPACING = "number_of_spaces"
HEADERLINES = "number_of_lines"
HTMLTABLE = "Yes
| No"
BORDER = "Yes I No" COLHEADERS = "Yes | No"
STARTROW = "row_number">
</CFTABLE>
В табл. 11.5
представлено описание атрибутов тега <CFTABLE>.
Таблица
11.5. Описание атрибутов тега <CFTABLE>
Атрибут |
Описание |
||
QUERY |
Имя запроса.
Обязательный атрибут. Для вывода результатов запроса внутри блока
<CFTABLE> |
||
MAXROWS |
Максимальное
количество записей, которое следует выводить внутри блока <CFTABLE>.
Необязательный атрибут |
||
COLSPACING |
Пространство
между колонками. Необязательный атрибут. По умолчанию равен 2 |
||
HEADERLINES |
Высота между
заголовком и первым рядом. По умолчанию значение равно 2, что соответствует
одному интервалу |
||
HTMLTABLE |
Формирование
страницы в формате HTML 3.0. Необязательный атрибут. Возможные значения: • Yes— да; •
No — нет (по умолчанию) |
||
BORDER |
Рамка таблицы.
Необязательный атрибут. Имеет смысл использовать при включении атрибута
HTMLTABLE. Возможные значения: • Yes — да;
• No — нет (по умолчанию) |
||
COLHEADERS |
Отображение
заголовка таблицы. Необязательный атрибут. Возможные
значения: • Yes— да; • No — нет (по умолчанию) |
||
STARTROW |
Номер записи,
с которой следует выводить полученные данные. Необязательный атрибут |
||
Синтаксис:
<CFCOL HEADER
= "coluitin_header_text"
WIDTH = "number_indicating_width_of_colurrm"
ALIGN = "Left | Right | Center" TEXT = "text">
В табл. 11.6
представлено описание атрибутов тега <CFCOL>.
Таблица
11.6. Описание атрибутов тега <CFCOL>
Атрибут |
Описание |
||
HEADER |
Текст заголовка
колонки. Обязательный атрибут |
||
WIDTH |
Ширина колонки
в символах. Необязательный атрибут. По умолчанию значение равно 20 |
||
ALIGN |
Выравнивание
текста внутри колонки. Необязательный атрибут. Возможные значения: • Left — по левому краю (по умолчанию); • Right — по правому краю; • Center — по
центру |
||
TEXT |
Текст содержимого
колонки. Текст может состоять из различных комбинаций и включать HTML-теги.
Необязательный атрибут |
||
Пример
сочетания тегов <CFTABLE> и <CFCOL>
Мы не будем
здесь приводить полный код страницы, покажем лишь, как можно было бы решить
предыдущую задачу, где необходимо вывести все круизы, зарегистрированные в базе
данных.
Напомним,
что для решения данной задачи предварительно был построен запрос вот таким образом:
<CFQUERY
NAME="GetTour" DATASOURCE="tapplication.dsn#">
SELECT Key_tou, Name_tou, PointDepart_tou,
NuraLandingPlaces_tou, Time_tou, CostAdult_tou,
CostChildren_tou,
CostSenior_tou FROM Tour
</CFQUERY>
Далее выведем
список полученных данных с использованием тегов
<CFTABLE>
И <CFCOL>:
<CFTABLE QUERY="GetTour" COLHEADERS="Yes"
COLSPACING="0"
HEADERLINES="1">
<CFCOL HEADER = "<b>Name tour</b>"
WIDTH = "27" ALIGN = "Left" TEXT = "
<a href='AdminUpdateTour.cfm?key_tou=
#Key_tou#'>tName_tou#</a>">
<CFCOL HEADER = "<b>Point of departure</b>"
WIDTH = "28"
ALIGN = "Left"
TEXT = "#PointDepart_tout">
<CFCOL HEADER = "<b>Places</b>" WIDTH = "5"
ALIGN = "Right"
TEXT = "#NumLandingPlaces tou#">
<CFCOL HEADER
= "<b>Time</b>" WIDTH = "9" ALIGN = "Right"
TEXT = "#Time_tou#-hr">
<CFCOL HEADER = "
<b>Adults</b>" WIDTH = "9"
ALIGN = "Right"
TEXT = "$#CostAdult_tou#">
<CFCOL HEADER = "
<b>Children</b>" WIDTH = "9"
ALIGN = "Right"
TEXT = "$#CostChildren_tout">
<CFCOL HEADER = "
<b>Seniors</b>" WIDTH = "9"
ALIGN = "Right"
TEXT = "$#CostSenior_tou#">
<CFCOL HEADER = "
<b>Note</b>" WIDTH = "6"
ALIGN = "Center"
TEXT = "<a href='AdminNoteTour.
cfm?key_tou=iKey_tou#'
target= '_blank' XFONT face=' Wingdings'>
±</FONTx/a>">
</CFTABLE>
Для модификации
данных в ColdFusion можно воспользоваться несколькими вариантами: SQL-командой
UPDATE внутри уже описанного нами тега <CFQUERY>, тегом <CFUPDATE>,
а также тегом <CFGRID>, указываемого в рамках тега <CFFORM>. В данной
главе будут рассмотрены только первые два способа.
Прежде чем
привести пример по модификации данных, рассмотрим синтаксис SQL-команды UPDATE.
Синтаксис:
UPDATE table_namelSET column_namel = expressionl
[, column_name2 = expression2 ...] WHERE filter_conditi'onl
[AND | OR filter_condition2
...]]
Параметры:
Задает таблицу,
в которой необходимо изменить записи.
Задает обновляемые
столбцы и их новые значения. Если предложение WHERE опущено, каждая строка одного
столбца обновляется одним и тем же значением.
Условие filter_condition
задает критерий, которому должны удовлетворять изменяемые записи. Можно включить
сколько угодно условий фильтрования,
объединяя их операторами AND и OR. Можно также использовать оператор NOT, инвертирующий
значение логического выражения.
Замечание
Команда
UPDATE может модифицировать записи только в одной таблице.
Предположим,
нам необходимо организовать возможность модификации данных для уже зарегистрированных
покупателей.
В этом случае
требуется создать форму для редактирования данных с последующим изменением этих
данных для конкретного покупателя. Тогда в нашем случае запрос в ColdFusion
будет выглядеть следующим образом:
<CFQUERY NAME="UpdateTraveler" DATASOURCE="#application.dsn#">
UPDATE Traveler
SET EMail_tra
= '#Form.EMail#',
FirstName_tra = 'IForm.FirstNamel',
LastName_tra = 'lForm.LastName#',
Middlelnitial_tra = '#Form.MiddleInitial#',
Password_tra = '#Form.Password!',
PhoneNum_tra = 'ttForm.PhoneNum#'
WHERE Key_tra
= tSession.traveler.id# </CFQUERY>
Здесь в предложении
SET перечислены обновляемые столбцы и их новые значения.
Следующим
этапом обновляем переменную сессии session.traveler.name, поскольку значение
этой переменной есть ни что иное, как сочетание значений двух модифицируемых
полей, которые могли быть изменены. После чего открываем основную страницу и
с помощью тега <CFEXIT> прекращаем выполнение последующего кода текущей
страницы. Этот код таков:
<CFSET Session.traveler.name = #Form.FirstName#$" "&#Form.LastName#>
<META HTTP-EQUIV="Refresh"
CONTENT="0;URL=BuyTickets.cfm"> <CFEXIT>
В листинге
11.7 представлен полный код страницы UpdateTra.cfm, позволяющей решить поставленную
перед нами задачу.
Листинг
11.7. Код страницы UpdateTra.cfm
<HTML>
<HEAD>
<CFINCLUDE
TEMPLATE = "MyHEAD.cfm">
<link rel="STYLESHEET"
type="text/css" href="main.css">
<script type="text/javascript"
language="JavaScript"
src="main. js"></script> <style type="text/css">
<! --
#Update { position:absolute;
left:20; top:140; width:200; height:100; margin:0;z-index:0;}
</style>
<script.language="JavaScript">
if (ie) (document.write('<link
rel="stylesheet" type="text/css"
href="main_ie.css" title="master">');} </script> </HEAD>
<BODY onload="init(1)"
bgcolor="<CFOUTPUT>iapplication.BGColorPage#</CFOUTPUT>" text="Black" alink="#107098" link="#OC1C47" vlink="#003366">
<CFINCLUDE TEMPLATE = "BasicBlock.cfm">
<CFIF isDefined( "Session', traveler, id") >
<CFIF isDefined("Form.EMail")>
<CFSET Disuccessful = 1>
<CFSET msgError
= "Warning Error!">
<CFIF Len(Form.EMail) le 5 and Form.EMail does not contain "@">
<CFSET msgError = msgError & "<br>" & #application.msgErrorl#>
<CFSET Disuccessful
= 0> </CFIF> <CFIF Len(Form.Password) le 4>
<CFSET msgError - msgError & "<br>" & #application.msgError2#>
<CFSET Disuccessful
= 0> </CFIF> <CFIF IsNumeric(Form.Password)>
<CFSET msgError = msgError & "<br>" & lapplication.msgError3#>
<CFSET Disuccessful = 0> </CFIF>
<CFIF Form.Password
not equal Form.Confirm>
<CFSET msgError = msgError & "<br>" & tapplication.msgError4#>
<CFSET Disuccessful
= 0> </CFIF> <CFIF Len(Form.FirstName) le 0>
<CFSET msgError = msgError & "<br>" & #application.msgError5#>
<CFSET Disuccessful
= 0> </CFIF> <CFIF Len(Form.LastName) le 0>
<CFSET msgError = msgError & "<br>" & #application.msgError6#>
<CFSET Disuccessful
= 0> </CFIF>
<CFIF YesNoFormat
(Disuccessful) equal "No"> <!---Сшибки (Errors)--->
<CFSET email = #Form.EMail#> <CFSET fname = #Form.FirstName#>
<CFSET Iname = #Form.LastName#>
<CFSET middle = #Form.MiddleInitial#>
<CFSET phonen
= #Form.PhoneNumtt> <CFELSE>
<!--- Обновление
записи (Update record) --->
<CFQUERY NAME="UpdateTraveler" DATASOURCE="#application.dsn#">
UPDATE Traveler
SET EMail_tra = '#Form.EMail#',
FirstName_tra = '#Form.FirstNarae#',
LastName_tra = '#Form.LastName#',
Middlelnitial_tra = '#Form.MiddleInitial#',
Password_tra = '#Form.Password#',
PhoneNum_tra = '#Form.PhoneNum#'
WHERE Key_tra = tSession.traveler.id# </CFQUERY>
<CFSET Session,
traveler, name = #Form. FirstName# & " " &
#Form.LastName#>
<META HTTP-EQUIV="Refresh"
CONTENT="0;URL=BuyTickets.cfm"> <CFEXIT> </CFIF> <CFELSE>
<CFQUERY
NAME="GetTraveler" DATASOURCE="#application.dsn#"> SELECT
*
FROM Traveler
WHERE Key_tra = ISession.traveler.id# </CFQUERY>
<CFOUTPUT QUERY="GetTraveler"> <CFSET email = #EMail_tra#>
<CFSET fname = #FirstName_tra#> <CFSET Iname = lLastName_tra#>
<CFSET middle = #MiddleInitial_tra#> <CFSET phonen = #PhoneNum_tra#>
<CFSET msgError
= ""> </CFOUTPUT> </CFIF> <DIV id="Update">
<FORM action='UpdateTra.cfm' method='post' name='forml'>
<TABLE border='0'
cellspacing='0' cellpadding='0'> <TR>
<TR><TD
colspan="2" height=l></TD>
<TD colspan="4" bgcolor="#122c6d" height=l></TD></TR>
<TD class="menleft"><a
href="BuyTickets.cfm"
onMouseOver="mouse_over_bull('bul12',
'Update'}; window.status='Sign Up';
return true" onMouseOut="mouse_out_bull('bul12',
'Update'); window.status=''; return true">
<img name="bull2"
src="bullet.gif" width="20"
height="20" border="0"></a></td>"
<TD width="55"><a
href="BuyTickets.cfm"
onMouseOver="mouse_over_bull('bul12', 'Update');"
onMouseOut="mouse_out_bull('bul12',
'Update');"
class="menleft">
Log In</a></TD>
<TD bgcolor="#122c6d"></TD>
<TD class="menleft">
<img name="bulll"
src="bullet2.gif" width="20"
height="20" border="0"></TD>
<TD width="82" class="menleft">Update</TD>
<TR><td
colspan="2" bgcolor="#122c6d" height=l></TD>
<TD colspan="2"
height=l></TD></TR> </TR> </TABLE>
<table width="300" border="0" cellspacing="2" cellpadding="0">
<TR><TD
colspan="2" align="center" class="txtError">
<CFOUTPUT>#msgError#</CFOUTPUT></TD></TR>
<TR><TD
align="right" class="txtForm1">
E-Mail (Login)</td><td width="215" class="txtForm1">
<input name='EMail'
size='16'
value="<CFOUTPUT>#email#</CFOUTPUT>"> *</TD></TR>
<TR><TD align="right" class="txtForml"> Password</td>
<td class="txtForml">
<input type='password' name='Password'
size=' 16'> *</TD></TR>
<TR><TD
align="right" class="txtForml">
Confirm</tdxtd
class="txtForml">
<input type='password'
name='Confirm'
size=' 16'> *</TD></TR>
<TR><TD
align="right" class="txtForml"> First Name</tdxtd
class="txtForml"> <input name='FirstName' size='16'
value="<CFOUTPUT>#fname#</CFOUTPUT>"> *
</TD></TR>
<TRXTD align="right" class="txtForml"> Last Name</td>
<td class="txtForml">
<input name='LastName' size='16'
value="<CFOUTPUT>#lname#</CFOUTPUT>"> *</TD></TR>
<TRXTD align="right" class="txtForml"> Middle Initial</td>
<td> <input
name='MiddleInitial' size='l'
value="<CFOUTPUT>#middle#</CFOUTPUT>"></TD></TR>
<TR><TD align="right" class="txtForml"> Phone Num.</td>
<td> <input
name='PhoneNura' size='10'
value="<CFOUTPUT>#phonen#</CFOUTPUT>"></TD></TR>
<TR><td
align="right">
<input type='submit' value=' Set '></TD><TD> <input type='reset' value='Reset'></TD></TR>
</TABLE>
</FORM> </DIV>
<CFELSE>
<META HTTP-EQUIV="Refresh" CONTENT="0;UR]>BuyTickets.cfm"> </CFIF>
</BODY>
</HTML>
Отметим,
что сообщения об ошибках определены в конфигурационном файле Application. cfm
так, как это показано в разд. "Пример файла Application. cfm" гл.
10.
Также для
модификации данных в ColdFusion можно использовать тег <CFUPDATE>, о чем
и пойдет речь в следующем разделе с предварительным описанием этого тега.
Синтаксис:
<CFUPDATE
DATASOURCE = "ds_name" DBTYPE = "type" OBSERVER = "dbms"
DBNAME = "database
name"
TABLENAME =
"tbl_name"
CONNECTSTRING
= "connection string"
TABLEOWNER =
"owner"
TABLEQUALIFIER
= "tbl_qualifier"
USERNAME = "username"
PASSWORD = "password"
PROVIDER = "COMProvider"
PROVIDERDSN
= "datasource"
FORMFIELD3 =
"formfieldl, formfield2, ...">
Атрибуты
тега <CFUPDATE> полностью идентичны с атрибутами уже описанного тега <CFINSERT>
(см. табл. 11.3).
Чтобы продемонстрировать
использование тега <CFUPDATE>, предназначенного для модификации данных,
рассмотрим пример, позволяющий изменять информацию об уже зарегистрированных
экскурсиях и круизах.
Для решения
данной задачи необходимо создать форму, предназначенную для редактирования необходимых
данных с целью их последующего изменения по выбранному круизу. Тогда для нашего
примера код модификации данных будет выглядеть следующим образом:
<CFUPDATE DATASOURCE = "#application.dsn#"
TABLENAME = "Tour"
FORMFIELDS = "Key_tou,Name_tou,PointDepart_tou,
NumLandingPlaces_tou,Time_tou,CostAdult_tou,
CostChildren_tou,CostSenior_tou,Photo_tou,Note_tou">
В листинге
11.8 приведен полный код страницы AdmmUpdateTour.cfm, позволяющей решить описанную
выше задачу.
Листинг
11.8. Код страницы AdminUpdateTour.cfm
<HTML>
<HEAD>
<CFINCLUDE
TEMPLATE = "MyHEAD.cfm">
<link rel="STYLESHEET"
type="text/css" href="main.ess">
<script type="text/javascript"
language="JavaScript"
src="main.
js"></script> <sty'le type="text/ess"> <! --
#Tour { position:absolute;
left:20; top:140; width:200; height:100; margin:0; z-index:0;}
</style>
<script language="JavaScript">
if (ie) {document.write('<link
rel="stylesheet" type="text/css"
href="main_ie.css"
title="master">'};} </script> </HEAD> <BODY onload="init(1)"
bgcolor="<CFOUTPUT>#application.BGColorPage#
</CFOUTPUT>" text="Black" alink="#107098" link="#OC1C47" vlink="#003366">
<CFINCLUDE TEMPLATE = "BasicBlock.cfm">
<CFIF isDefined("key_tou")>
<CFIF isDefined("Form.Name_tou")> <CFSET Disuccessful = 1>
<CFSET msgError
= "Warning Error!">
<CFIF Len(Form.Name_tou)
le 0 or Len(Form.PointDepart_tou) le 0 or Len(Form.NumLandingPlaces_tou) le
0 or Len(Form.Time_tou) le 0 or Len(Form.CostAdult_tou) le 0 or Len(Form.CostChildren_tou)
le 0 or Len(Form.CostSenior_tou) le 0> <CFSET msgError = msgError &
"<br>" & "The fields marked with
a symbol *, should not be empty!">
<CFSET Disuccessful
= 0> </CFIF>
<CFIF YesNoFormat(Disuccessful)
equal "No"> <!--- Errors --->
<CFSET Name_tou = IForm.Name_tou#>
<CFSET PointDepart_tou = #Form.PointDepart_tou#>
<CFSET NumLandingPlaces_tou = #Form.NumLandingPlaces_tou#>
<CFSET Time_tou = #Form.Time_tou#>
<CFSET CostAdult_tou = #Form.CostAdult_tou#>
<CFSET CostChildren_tou = #Form.CostChildren_toutt>
<CFSET CostSenior_tou = #Form.CostSenior_tou#>
<CFSET Photo_tou = #Form.Photo_toui>
<CFSET Note_tou
= #Form.Note_tou#> <CFELSE>
<!--- Обновление
записи (Update record) --->
<CFUPDATE
DATASOURCE = "#application.dsn#" TABLENAME = "Tour" FORMFIELDS
= "Name_tou,PointDepart_tou,
NumLandingPlaces_tou,
Time_tou,CostAdult_tou,CostChildren_tou,
CostSenior_tou,Photo_tou,Note_tou">
<META HTTP-EQUIV="Refresh" CONTENT="0;URL=AdminListTour.cfm">
<CFEXIT>
</CFIF> <CFELSE>
<CFSET msgError
= "">
<CFQUERY
NAME="GetTour" DATASOURCE="tapplication.dsn#">
SELECT *
FROM Tour WHERE Key_tou = '#key_tou#' </CFQUERY>
<CFOUTPUT
QUERY="GetTour">
<CFSET Name_tou
= #Name_tou#>
<CFSET PointDepart_tou
= #PointDepart_tou#>
<CFSET NumLandingPlaces_tou
= #NumLandingPlaces_tou#>
<CFSET Tirae_tou
= #Time_tou#>
<CFSET CostAdult_tou
= #CostAdult_tou#>
<CFSET CostChildren_tou
= #CostChildren_tou#>
<CFSET CostSenior_tou
= #CostSenior_tou#>
<CFSET Photo_tou
= #Photo_tou#>
<CFSET Note_tou
= #Note_tou#> </CFOUTPUT> </CFIF>
<DIV id="Tour">
<FORM action='AdminUpdateTour.cfm' method='post' name='form1'>
<TABLE width="370"
border="0" cellspacing="0" cellpadding="0">
<TR>
<TR><TD
colspan="2" height=l></TD>
<TD colspan="4"
bgcolor="#122c6d" height=l></TD></TR>
<TD class="menleft"><a
href="AdminListTour.cfm"
onMouseOver="mouse_over_bull('bull2', 'Tour');
window.status='List Tour'; return true"
onMouseOut="mouse_out_bull('bull2', 'Tour');
window.status=''; return true">
<IMG name="bull2"
src="bullet.gif" width="20" height="20"
border="0"></a></TD>
<TD width="155">
<a href="AdminListTour.cfm"
onMouseOver="mouse
over bull('bull2', 'Tour');"
onMouseOut="mouse_out_bull('bull2',
'Tour');
"class="menleft"> List Tour</a></TD>
<TD bgcolor="#122c6d"></TD>
<TD class="menleft">
<IMG name="bulll"
src="bullet2.gif" width="20" height="20"
border="0"></td>
<TD width="215"
class="menleft">
Update Tour (<a
href="javascript:del('AdminDeleteTour
.cfm?key_tou=<CFOUTPUT>#key_tou# </CFOUTPUT>')
;" class="menleft_u">Delete
Tour</a>)
</TD>
<TR><td colspan="2" bgcolor="#122c6d" height<=l></TD>
<TD colspan="2"
height=l></TD></TR> </TR> </TABLE>
<TABLE widtb="390" border="0" cellspacing="2" cellpadding="0">
<TR><td
colspan="2" align="center" class="txtError">
<CFOUTPUT>#msgError#</CFOUTPUT></TD></TR>
<TR><td
align="right" class="txtForm1">
Name tour.</td><td width="230" class="txtForml">
<input name='Name_tou'
size='30'
value="<CFOUTPUT>#Name_tou#</CFOUTPUT>">Snbsp;* </TD></TR>
<TR><TD
align="right" class="txtForml">
Point of departure</tdxtd class="txtForml">
<input name='PointDepart_tou'
size='30'
value="<CFOUTPUT>#PointDepart_toul
</CFOUTPUT>"> * </TD></TR>
<TR><TD
align="right" class="txtForml">
Number of landing places</td>
<td class="txtForml">
<input name='NumLandingPlaces_tou'
size='6'
value="<CFOUTPUT>#NumLandingPlaces_toul
</CFOUTPUT>"> * </TD></TR>
<TR><TD
align="right" class="txtForml">
Time in tour</td><td class="txtForml">
<input name='Time_tou'
size='2'
value="<CFOUTPUT>#Time_tou#
</CFOUTPUT>"> hours,Snbsp;*
</TD></TR>
<TR><TD
align=" right" class="txtForml">
Cost for adults</tdxtd class="txtForml">
<input name='CostAdult__tou'
size='6'
value="<CFOUTPUT>#CostAdult_tou#
</CFOUTPUT>"> $, * </TD></TR>
<TR><TD
align="right" class="txtForm1">
Cost for children</tdxtd class="txtForml">
<input name='CostChildren_tou'
size='6'
value="<CFOaTPUT>#CostChildren_tou#
</CFOUTPUT>"> $, * </TD></TR>
<TR><TD
align="right" class="txtForml">
Cost for senior citizens</tdxtd class="txtForml">
<input name='CostSenior_tou'
size='6'
value="<CFOUTPUT>#CostSenior_tou#
</CFOUTPUT>"> $, * </TD></TR>
<TR><TD
align="right" class="txtForml">
Photo</TD><TD>
<input name= ' Photo__tou ' size='23'
value="<CFOUTPUT>iPhoto_tou#</CFOUTPUT>"></TD></TR>
<TR><TD
align="right" class="txtForml">
Note</TD><TD>
<textarea name = "Note_tou" cols = "33"
rows = "4"><CFOUTPUT>#Note
tou#</CFOUTPUT>
</textarea>
</TD></TR>
<TR><TD><input
type="Hidden" nanie="key_tou"
value="<CFOUTPUT>#key_tou#</CFOUTPUT>"></td><td>
<TR><TD
align="right">
<input type=' submit' value=' Set '></TD><TD>
<input type=' reset' value= ' Reset '></TD></TR>
</TABLE>
</FORM>
</DIV>
<CFELSE>
<META HTTP-EQUIV="Refresh"
CONTENT="0;URL=AdminListTour.cfm"> </CFIF> </BODY>
</HTML>
Обращаем
ваше внимание, что на страницу AdminUpdateTour.cfm пользователь попадает со
страницы AdminListTour.cfm, откуда и передается переменная key_tou, с помощью
которой производится выборка необходимых данных.
В рассмотренном
примере встречается ссылка на страницу AdminDeleteTour.cfm, предназначенную
для удаления текущей записи, о чем, собственно говоря, и пойдет речь далее.
Для удаления
данных в ColdFusion существует опять же несколько способов: применение SQL-команды
DELETE внутри уже описанного нами тега <CFQUERY>, указание тега <CFGRID>,
используемого в рамках тега <CFFORM>. Впрочем, тег <CFGRID> позволяет
только визуализировать процесс удаления данных, а для непосредственного удаления,
так или иначе, необходимо использовать команду DELETE. В данной главе будет
рассмотрен только первый способ.
Синтаксис:
DZLETE FROM
table_name
[WHERE filter_conditionl
[AND | OR filter_condition2 ...]]
Параметры:
Задает таблицу,
в которой предполагается удаление записей.
Указывает
на удаление только определенных записей.
Условие fiiter_condition
устанавливает критерий, которому должны удовлетворять записи, предназначенные
для удаления. Можно задать сколько угодно условий фильтрования, объединяя их
с помощью операторов AND и OR. Можно также пользоваться оператором NOT, инвертирующим
значение логического выражения.
Предположим,
нам необходимо в режиме обновления данных по тому или иному круизу предоставить
возможность удалить текущую запись.
В этом случае требуется лишь установить ссылку на страницу, отвечающую за удаление данных с обязательным включением в URL-адрес значения уникального ключа для удаления только текущей записи. К примеру, так:
<а href="AdminDeleteTour.cfm?key_tou= <CFOUTPUT>#key_tou#
</CFOUTPUT>')
">Delete Tour</a>
А уже непосредственно
запрос на удаление в указанной странице может выглядеть следующим образом:
<CFQUERY
NAME="DeleteTour" DATASOURCE="#application.dsn#">
DELETE Tour
WHERE Key_tou = '#key_tou#' </CFQUERY>
Однако правильно
было бы перед удалением записи обращаться к пользователю за подтверждением удаления,
и здесь могут быть разные решения.
Для реализации
подтверждения на удаление мы несколько преобразуем ссылку:
<а
href="javascript:del('AdminDeleteTour.cfm?key_tou=
<CFOUTPUT>#key_tou#</CFOUTPUT>');"
class="menleft_u">Delete
Tour</a>
где del —
заранее созданная функция и помещенная в основной файл JavaScript main.js. Приведем
код этой функции:
function del(url)
{ if(ie){
_del = self.showModalDialog
("DialogQuestion.cfm?text_=You really
want to delete the current record?", null,
"status.:no; center: yes;help:no;
minimize:no;maximize:no;border:thin;
statusbar:no;dialogWidth:305px;
dialogHeight:110px");
if(_del==true) {
location.href=url;
} } else {
location.href=url;
} }
Необходимо
отметить, что с помощью данной функции мы открываем модальное окно только для
браузера MS Internet Explorer. Для остальных же браузеров запись удаляется без
подтверждения. Впрочем, у вас есть возможность исправить данный недочет и самостоятельно
решить эту задачу. Мы же приведем пример страницы DialogQuestion.cfm, исполняющей
роль диалога подтверждения удаления записи.
Листинг
11.9. Код страницы DialogQuestion.cfm
<HTML>
<HEAD>
<CFINCLUDE
TEMPLATE = "MyHEAD. cfm">
<link rel="STYLESHEET"
type=" text /ess" href="main.css">
<style type="text/css">
<! —
fpic_ {position:
absolute; left: 10; top: 10; margin: 0;} — >
</style>
</HEAD> <BODY bgcolor="#COCOCO">
<div id="pic_">
<img src="question_icon.gif
">
<br>
<p class="dialog_">
snbsp;
Snbsp;
Snbsp; Snbsp;
Snbsp; <CFIF isDefined("URL.text_")>
<CFOUTPUT>#URL
. text_#</CFOUTPUT> </CFIF>
</р>
<р ALIGN="ccnter">
snbsp;
<BUTTON ID="btnDelYes" style="height: 23; ">
<SPAN class="dialog"> Yes Snbsp; </BUTTON>
finbsp; Snbsp;
<BUTTON ID="btnDelNo"
style="height:23;">
<SPAN class="dialog">
No </BUTTON>
</p>
<SCRIPT LANGUAGE="VBScript">
<! —
Sub btnDelYesJDnClick self. returnValue=true self
. close
End Sub
Sub btnDelNo_OnClick self. returnValue=false self
. close
End Sub — >
</SCRIPT>
</BODY> </HTML>
В заключение
описания удаления данных посредством ColdFusion приведем пример страницы AdminDeleteTour.cfm,
где, в общем-то, и совершается "обряд" удаления выбранного круиза.
Листинг
11.10. Код страницы AdminDeleteTour.cfm
<HTML>
<HEAD>
<CFINCLUDE TEMPLATE = "MyHEAD. cfm"> </HEAD>
<BODY bgcolo"r="<CFOUTPUT>#application.BGColorPage#</CFOUTPUT>"
text="Black"
alink="#107098" link="#OC1C47" vlink="#003366">
<CFIF isDefined("key_tou")>
<CFQOERY
NAME="DeleteTour" DATASOURCE="#application.dsn#">
DELETE Tour
WHERE Key_tou = '#key_tou#' </CFQUERY> </CFIF>
<META HTTP-EQUIV="Ref resh" CONTENT="0;URL=AdminListTour . cfm">
</BODY>
</HTML>
Отметим лишь,
что по мере удаления записей пользователь возвращается к списку еще пока существующих
круизов.
Транзакция
— это логическая единица работы, т. е. транзакция в приложении обеспечивает
защиту путем выделения секции программного кода в качестве единицы восстановления.
Рассмотрим
пример. Предположим, что таблица TOUR включает дополнительный атрибут TotaiTraveier,
представляющий собой общее число путешественников для каждого круиза. Значение
TotaiTraveier для любого круиза должно быть равным сумме купленных билетов.
Покупка же билетов регистрируется в таблице TICKET. Данный пример предполагает,
что речь идет о выполнении двух операций: добавлении новой записи в таблицу
TICKET и модификации значения поля TotaiTraveier в таблице TOUR для выбранного
круиза. При этом в базе данных между двумя указанными операциями временно, нарушается
требование, что значение TotaiTraveier для круиза равно сумме купленных билетов
на конкретный круиз. Таким образом, логическая единица работы — не просто одиночная
операция системы баз данных, а скорее согласование нескольких таких операций.
И не допустимо, чтобы одна из операций была выполнена, а другая нет, поскольку
база данных остается в несогласованном состоянии. В идеальном случае должны
быть выполнены обе операции. Однако нельзя обеспечить абсолютную гарантию, что
так и случится. Не исключена вероятность, что система может дать сбой между
двумя операциями, или же на второй операции произойдет арифметическое переполнение
и т. д. Система же, поддерживающая процесс транзакции, гарантирует, что если
во время выполнения неких операций произошла ошибка, то все результаты операций
будут аннулированы. Таким образом, транзакция или выполняется целиком, или полностью
отменяется.
Для установки
транзакции в ColdFusion необходимо использовать тег <CFTRANSACTION>.
Синтаксис:
<CFTRANSACTION
ACTION = "Begin | Commit I Rollback"
ISOLATION =
"Read_Uncommitted | Read_Committed |
Repeatable_Read
I Serializable"> </CFTRANSACTION>
В табл. 11.7
представлено описание атрибутов тега <CFTRANSACTION>.
Таблица
11.7. Описание атрибутов тега <CFTRANSACTION>
Атрибут |
Описание |
|
ACTION |
Действие. Необязательный
атрибут. Возможные значения: • Begin — начать транзакцию (по умолчанию); • Commit — применить
изменения, совершенные с момента начала транзакции; • Rollback —
отменить все изменения, сделанные с момента начала транзакции |
|
ISOLATION |
Уровень изоляции.
Необязательный атрибут. Возможные значения: • Read Uncommitted—
незавершенное считывание, предназначено для "неаккуратных"
считываний; • Read Committed
— завершенное считывание; • Repeatable Read — повторяемое считывание; • Serializable
— способность к упорядочению, по сути, является единственным безопасным
уровнем |
|
В пределах
блока транзакции можно применять изменения, совершенные с момента начала транзакции,
указав
<CFTRANSACTION
ACTION = "commit"/>
либо отменить
все изменения, добавив
<CFTRANSACTION
ACTION = "rollback"/>
Усложним
задачу удаления круизов. В следующем примере (листинг 11.11) с использованием
транзакции удаляется запись со сведениями о выбранном круизе и все связанные
записи с данными о расписании и забронированных билетах.
Листинг
11.11. Код страницы AdminDeleteTour.cfm с добавлением блока транзакции
<HTML>
<HEAD>
<CFINCLUDE TEMPLATE = "MyHEAD.cfm"> </HEAD>
<BODY bgcolor="<CFOUTPUT>#application.BGColorPage#</CFOUTPUT>"
text="Black"
alink="#107098" link="#0C1C47" vlink="#003366">
<CFIF isDefined("key_tou")>
<CETRANSACTION
ACTION="Begin">
<CFQUERY NAME="DeleteTicket" DATASOURCE="#application.dsn#">
DELETE Ticket
WHERE Key_tou
= '#key_tou#' </CFQUERY>
<CFQUERY NAME="DeleteSchedule" DATASOURCE="#application.dsn#">
DELETE Schedule_
WHERE Key_tou
= '#key_tou#' </CFQUERY>
<CFQUERY NAME="DeleteTour" DATASOURCE="fapplication.dsn#">
DELETE Tour
WHERE Key_tou
= '#key_tou#' </CFQUERY>
<CFTRANSACTION ACTION="Commit"/> </CFTRANSACTION> </CFIF>
<META HTTP-EQUIV="Refresh"
CONTENT="0;URL=AdminListTour.cfm">
</BODY>
</HTML>
Если при
выполнении одной из команд DELETE возникает ошибка, транзакция выполнит откат,
что позволит избежать конфликтов.
В заключение
следует отметить, что SQL-запросы являются одним из главных инструментов работы
с данными, и если вам пока трудно дается написание SQL-запросов вручную, вы
можете прибегнуть к помощи конструктора запросов ColdFusion Studio, подробно
описанного в разд. "Базы данных" гл. 4. Подведем итог. В данной
главе мы познакомились и использовали CFML-теги:
<CFQUERY>,
<CFINSERT>, <CFTABE>, <CFCOL>, <CFUPDATE>, <CFTRANSACTION>.